繼昨天的藍芽的掃描與配對後,今天要接續來講藍芽的連線及等等會來發送個字串,首先一樣要先確認已加入藍芽的權限至Manifest中:
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
接著附上今天UI:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="240dp"
android:onClick="pairDevice"
android:text="配對"
android:textSize="28dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent" />
<EditText
android:id="@+id/editTextTextPersonName"
android:layout_width="400dp"
android:layout_height="50dp"
android:layout_marginBottom="60dp"
android:ems="10"
android:inputType="textPersonName"
android:hint="輸入傳送資料"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btn_send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="sendData"
android:text="傳送"
android:textSize="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.758"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
<Button
android:id="@+id/btn_disconnect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="斷線"
android:textSize="24dp"
android:onClick="disConnect"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.247"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
繼昨天設計完掃描與配對後,今天要來提提連線與斷線,首先我在ui寫了兩個按鈕:
傳送(監聽方法:sendData)、斷線(監聽方法:disConnect),傳送按鈕在傳送資料之前也會進行迴圈的連線,而連線(BluetoothDevice)的方法又可分為兩種:createInsecureRfcommSocketToServiceRecord(不安全連線)、createRfcommSocketToServiceRecord(安全連線),主要都是通過uuid去連(BluetoothDevice包含),而斷線的話只需要將socket設null,後面就會再重新去進行連線,接著附上這兩個監聽方法(sendData、disConnect)。
private BluetoothDevice device;
private BluetoothAdapter adapter;
private BluetoothSocket socket;
private ParcelUuid[] deviceUUid;
private OutputStream os;
private InputStream is;
//當按下傳送按鈕
public void sendData(View view){
try {
deviceUUid = device.getUuids();
Log.d("UUid",""+deviceUUid[0].getUuid());
Log.d("UUidSize",""+deviceUUid.length);
if(socket==null){
//連線方法1(不安全的連線)
// socket=device.createInsecureRfcommSocketToServiceRecord(deviceUUid[0].getUuid());
//連線方法2(安全的連線)
socket=device.createRfcommSocketToServiceRecord(deviceUUid[0].getUuid());
//迴圈進行連線
while(!socket.isConnected()){
try {
sleep(5000);
socket.connect();
Log.d("Connect State",""+socket.isConnected());
if(socket.isConnected()){
Toast.makeText(getApplicationContext(),"連線成功",Toast.LENGTH_SHORT).show();
}
}
catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
os=socket.getOutputStream();//輸入流
is=socket.getInputStream();//輸出流
}
os.write(dataText.getText().toString().getBytes("utf-8"));//utf-8寫入選擇裝置
Toast.makeText(getApplicationContext(),"已傳送字串",Toast.LENGTH_SHORT).show();
Log.d("sendText",""+dataText.getText().toString().getBytes());
}
catch (Exception e){
Log.d("Socket Error",""+e);
}
}
//藍芽斷線按鈕
public void disConnect(View view){
socket = null;
is = null;
os = null;
Toast.makeText(getApplicationContext(),"已斷線",Toast.LENGTH_SHORT).show();
}
接著便將這兩個監聽方法寫入昨天的程式中:
public class MainActivity extends AppCompatActivity {
private BluetoothDevice device;
private BluetoothAdapter adapter;
private String deviceName,deviceAddress;
private TextView showDevice;
private EditText dataText;
private BluetoothSocket socket;
private ParcelUuid[] deviceUUid;
private OutputStream os;
private InputStream is;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
showDevice = findViewById(R.id.textView);
dataText = findViewById(R.id.editTextTextPersonName);
//藍芽調配器
adapter = BluetoothAdapter.getDefaultAdapter();
// bluetooth抓到設備發送廣播
IntentFilter filter = new IntentFilter("android.bluetooth.devicepicker.action.DEVICE_SELECTED");
if(receiver!=null) {
registerReceiver(receiver, filter);//廣播
}
}
//廣播回傳
private BroadcastReceiver receiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
Log.d("taggg",""+action);
device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
deviceName = device.getName();
deviceAddress = device.getAddress(); // MAC address
showDevice.setText("配對裝置:" + deviceName + "\n" + "位址:" + deviceAddress);
try {
//回傳的選擇裝置進行配對
device.createBond();
} catch (Exception e) {
Log.e("CreateBondError", e.getMessage());
}
}
};
//配對按鈕
public void pairDevice(View view) {
//當藍芽未開啟
if(!adapter.isEnabled()) {
Toast.makeText(view.getContext(),"先開權限後再點擊按鈕",Toast.LENGTH_SHORT).show();
//打開藍芽窗(問你是否打開藍芽)
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);
startActivity(intent);
}
else{
//藍芽scanner
Toast.makeText(view.getContext(),"PairDevice",Toast.LENGTH_SHORT).show();
Intent bluetoothPicker = new Intent("android.bluetooth.devicepicker.action.LAUNCH");
startActivity(bluetoothPicker);
/*打開手機藍芽頁面
Intent intentSettings = new Intent();
intentSettings.setAction(android.provider.Settings.ACTION_BLUETOOTH_SETTINGS);
startActivity(intentSettings);
*/
}
}
//當按下傳送按鈕
public void sendData(View view){
try {
deviceUUid = device.getUuids();
Log.d("UUid",""+deviceUUid[0].getUuid());
Log.d("UUidSize",""+deviceUUid.length);
if(socket==null){
//連線方法1(不安全的連線)
// socket=device.createInsecureRfcommSocketToServiceRecord(deviceUUid[0].getUuid());
//連線方法2(安全的連線)
socket=device.createRfcommSocketToServiceRecord(deviceUUid[0].getUuid());
//迴圈進行連線
while(!socket.isConnected()){
try {
sleep(5000);
socket.connect();
Log.d("Connect State",""+socket.isConnected());
if(socket.isConnected()){
Toast.makeText(getApplicationContext(),"連線成功",Toast.LENGTH_SHORT).show();
}
}
catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
os=socket.getOutputStream();//輸入流
is=socket.getInputStream();//輸出流
}
os.write(dataText.getText().toString().getBytes("utf-8"));//utf-8寫入選擇裝置
Toast.makeText(getApplicationContext(),"已傳送字串",Toast.LENGTH_SHORT).show();
Log.d("sendText",""+dataText.getText().toString().getBytes());
}
catch (Exception e){
Log.d("Socket Error",""+e);
}
}
//藍芽斷線按鈕
public void disConnect(View view){
socket = null;
is = null;
os = null;
Toast.makeText(getApplicationContext(),"已斷線",Toast.LENGTH_SHORT).show();
}
}
要記得將藍芽裝置打開!